#include "AcDetector.h"

#include "ConfigManager.h"
#include "CommandParser.h"

//"(?:\\[(?<index>[0-9]{1,3})_(?<phase>[ABCabc])/(?<voltage>[0-9]{1,3})/(?<current>[0-9.]{1,7})\\])"
const std::regex AcDetector::pattern("(?:\\[([0-9]{1,3})_([ABCabc])/([0-9]{1,3})/([0-9.]{1,7})\\])");

AcDetector::AcDetector(DummyChannel& channel, const ExtendDeviceType& deviceType, const std::string& deviceActknowlege, const int32_t startIndex, const int32_t portCount) : ICurrentVoltageDetector(channel, deviceType, deviceActknowlege, startIndex, portCount) {

}


AcDetector::~AcDetector() {
    delete[] mcurrentVoltageInfos;
    mcurrentVoltageInfos = nullptr;
}


bool AcDetector::initialize() noexcept {
    ElecConfigInfo& elecInfo = ConfigManagerSingleton::instance().getExtendDeviceConfig().elecInfo;
    voltageAlert = elecInfo.voltageAlert;

    LoopSize_t* psize = const_cast<LoopSize_t*>(&mportCount);

    *psize = elecInfo.circuitCount;

    mcurrentVoltageInfos = new CurrentVoltageInfo[mportCount];

    setPhase(elecInfo.phaseString);

    mtrippingAlert = elecInfo.trippingAlert;
    mtrippingAlert.resize(mportCount, '1');

    return true;
}



bool AcDetector::updateInformation() {
    std::string result;
    mchannel.sendStringReturnString(mcommandBuilder, result);

    parseVoltageCurrent(result, mcurrentVoltageInfos);
    return true;
}



void AcDetector::parseVoltageCurrent(const std::string& dataString, CurrentVoltageInfo* pcurrentVoltageInfos){
    int index = 0;
    std::string portNoString;
    CurrentVoltageInfo* currentVoltageInfos = pcurrentVoltageInfos - 1;//第三方电流检测器回路从1开始，暂无法修改，故向上偏移1个元素
    CurrentVoltageInfo* pCurrentVoltageInfo = nullptr;
    std::sregex_iterator currentMatcherItarator(dataString.begin(), dataString.end(), pattern);
    std::sregex_iterator endMatcherItarator;

    while (currentMatcherItarator != endMatcherItarator) {
        portNoString = currentMatcherItarator->str(1);
        index = std::stoi(portNoString);
        pCurrentVoltageInfo = currentVoltageInfos + index;
        pCurrentVoltageInfo->portNo = portNoString;
        pCurrentVoltageInfo->phase = currentMatcherItarator->str(2).at(0);
        pCurrentVoltageInfo->voltage = currentMatcherItarator->str(3);
        pCurrentVoltageInfo->current = currentMatcherItarator->str(4);
        ++currentMatcherItarator;
    }
}



bool AcDetector::analysisVoltageAlert(void) {
    bool alert = false;
    bool noVoltage = true;
    std::string::size_type length = mportCount;
    for (std::size_t i = 0; i < length; ++i) {
        noVoltage &= NO_VOLTAGE == mcurrentVoltageInfos[i].voltage;
    }

    return voltageAlert && noVoltage;
}




bool AcDetector::analysisTrippingOperation(const std::string& loopStatus) {
    bool alert = false;
    bool noVoltage = true;
    std::string::size_type length = std::min(mportCount, loopStatus.size());
    for (std::size_t i = 0; i < length; ++i) {
        noVoltage &= NO_VOLTAGE == mcurrentVoltageInfos[i].voltage;
        if ((mtrippingAlert[i] & loopStatus[i] & 1) && NO_CURRENT == mcurrentVoltageInfos[i].current) {
            alert = true;
//            CommandParserSingleton::instance().sendCurrentAndVoltage();
            break;
        }
    }

    if (voltageAlert && noVoltage){
        alert = true;
    }

    return alert;
}



/*
analysisTrippingOperation(const std::string& loopStatus) {
    bool alert = false;
    bool noVoltage = true;
    std::string::size_type length = std::min(mportCount, loopStatus.size());
    for (std::size_t i = 0; i < length; ++i) {
        noVoltage &= NO_VOLTAGE == mcurrentVoltageInfos[i].voltage;
        if ((mtrippingAlert[i] & loopStatus[i] & 1) && NO_CURRENT == mcurrentVoltageInfos[i].current) {
            alert = true;
            break;
        }
    }

    if (voltageAlert && noVoltage){
        alert = true;
    }

    return alert;
}*/




/**
 * 设置所有相位
 * @param phaseString
*/
void AcDetector::setPhase(const std::string& phases) {
    mloopPhases.clear();
    mloopPhases.reserve(mportCount);
    size_t newLength = phases.length();

    size_t min = std::min(mportCount, newLength);

    mloopPhases.assign(phases, 0, min);
    if (mportCount > min) {
        for (size_t i = min; i < mportCount; ++i) {
            mloopPhases.push_back(('A' + (i % 3)));
        }
    }
    buildCommandAndSavePhase();
}


void AcDetector::buildCommandAndSavePhase() {
    mcommandBuilder.clear();

    mcommandBuilder.append("<AT_CHECK0_ELECT_");

    char buffer[3];
    snprintf(buffer, sizeof(buffer), "%02d", mportCount);

    mcommandBuilder.append(buffer, 2);
    for (const char& ch : mloopPhases) {
        mcommandBuilder.push_back('_');
        mcommandBuilder.push_back(ch);
    }
    mcommandBuilder.push_back('>');

    //CURRENT_PHASE_KEY+ getExtendNum()
}

